{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"red\">注</font>: 使用 tensorboard 可视化需要安装 tensorflow (TensorBoard依赖于tensorflow库，可以任意安装tensorflow的gpu/cpu版本)\n",
    "\n",
    "```shell\n",
    "pip install tensorflow-cpu\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:23.766049200Z",
     "start_time": "2024-07-24T10:45:14.134405100Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.9.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.2\n",
      "sklearn 1.5.0\n",
      "torch 2.3.1+cpu\n",
      "cpu\n"
     ]
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备\n",
    "\n",
    "```shell\n",
    "$ tree -L 2 archive \n",
    "archive\n",
    "├── monkey_labels.txt\n",
    "├── training\n",
    "│   ├── n0\n",
    "│   ├── n1\n",
    "│   ├── n2\n",
    "│   ├── n3\n",
    "│   ├── n4\n",
    "│   ├── n5\n",
    "│   ├── n6\n",
    "│   ├── n7\n",
    "│   ├── n8\n",
    "│   └── n9\n",
    "└── validation\n",
    "    ├── n0\n",
    "    ├── n1\n",
    "    ├── n2\n",
    "    ├── n3\n",
    "    ├── n4\n",
    "    ├── n5\n",
    "    ├── n6\n",
    "    ├── n7\n",
    "    ├── n8\n",
    "    └── n9\n",
    "\n",
    "22 directories, 1 file\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.742815900Z",
     "start_time": "2024-07-24T10:45:23.769046600Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load 1097 images from training dataset\n",
      "load 272 images from validation dataset\n"
     ]
    }
   ],
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor, Resize, Compose, ConvertImageDtype, Normalize\n",
    "\n",
    "\n",
    "from pathlib import Path\n",
    "\n",
    "DATA_DIR = Path(\"./archive/\")\n",
    "\n",
    "class MonkeyDataset(datasets.ImageFolder):\n",
    "    def __init__(self, mode, transform=None):\n",
    "        if mode == \"train\":\n",
    "            root = DATA_DIR / \"training\"\n",
    "        elif mode == \"val\":\n",
    "            root = DATA_DIR / \"validation\"\n",
    "        else:\n",
    "            raise ValueError(\"mode should be one of the following: train, val, but got {}\".format(mode))\n",
    "        super().__init__(root, transform) # 调用父类init方法\n",
    "        # self.imgs = self.samples # self.samples里边是图片路径及标签 [(path, label), (path, label),...]\n",
    "        self.targets = [s[1] for s in self.samples] # 标签取出来\n",
    "\n",
    "# 预先设定的图片尺寸\n",
    "img_h, img_w = 128, 128\n",
    "transform = Compose([\n",
    "    Resize((img_h, img_w)), # 图片缩放\n",
    "    ToTensor(),\n",
    "    # 预先统计的\n",
    "    Normalize([0.4363, 0.4328, 0.3291], [0.2085, 0.2032, 0.1988]),\n",
    "    ConvertImageDtype(torch.float), # 转换为float类型\n",
    "]) #数据预处理\n",
    "\n",
    "\n",
    "train_ds = MonkeyDataset(\"train\", transform=transform)\n",
    "val_ds = MonkeyDataset(\"val\", transform=transform)\n",
    "\n",
    "print(\"load {} images from training dataset\".format(len(train_ds)))\n",
    "print(\"load {} images from validation dataset\".format(len(val_ds)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.747401800Z",
     "start_time": "2024-07-24T10:45:25.743815400Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "['n0', 'n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7', 'n8', 'n9']"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数据类别\n",
    "train_ds.classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "{'n0': 0,\n 'n1': 1,\n 'n2': 2,\n 'n3': 3,\n 'n4': 4,\n 'n5': 5,\n 'n6': 6,\n 'n7': 7,\n 'n8': 8,\n 'n9': 9}"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_ds.class_to_idx"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.809942500Z",
     "start_time": "2024-07-24T10:45:25.749399800Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.810941Z",
     "start_time": "2024-07-24T10:45:25.767390200Z"
    }
   },
   "outputs": [],
   "source": [
    "# # 图片路径 及 标签\n",
    "# for fpath, label in train_ds.imgs:\n",
    "#     print(fpath, label)\n",
    "#     break\n",
    "#\n",
    "# #这个和之前的dataset完全一致\n",
    "# for img, label in train_ds:\n",
    "#     # c, h, w  label\n",
    "#     print(img, label)\n",
    "#     break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [],
   "source": [
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img[0:1, :, :].mean(dim=(1, 2))\n",
    "        std += img[0:1, :, :].std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "# 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.811941100Z",
     "start_time": "2024-07-24T10:45:25.776004300Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "# def cal_mean_std(ds):\n",
    "#     mean = 0.\n",
    "#     std = 0.\n",
    "#     for img, _ in ds:\n",
    "#         mean += img[1:2, :, :].mean(dim=(1, 2))\n",
    "#         std += img[1:2, :, :].std(dim=(1, 2))\n",
    "#     mean /= len(ds)\n",
    "#     std /= len(ds)\n",
    "#     return mean, std\n",
    "#\n",
    "# # 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.811941100Z",
     "start_time": "2024-07-24T10:45:25.787397500Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img[2:3, :, :].mean(dim=(1, 2))\n",
    "        std += img[2:3, :, :].std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "# 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.811941100Z",
     "start_time": "2024-07-24T10:45:25.798389700Z"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.853621500Z",
     "start_time": "2024-07-24T10:45:25.810941Z"
    }
   },
   "outputs": [],
   "source": [
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2)) #dim=(1, 2)表示计算均值后，宽和高消除（把宽和高所有的像素加起来，再除以总数）\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "# 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:45:25.854608600Z",
     "start_time": "2024-07-24T10:45:25.821612200Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "from torch.utils.data.dataloader import DataLoader    \n",
    "\n",
    "batch_size = 64\n",
    "# 从数据集到dataloader，num_workers参数不能加，否则会报错\n",
    "# https://github.com/pytorch/pytorch/issues/59438\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-24T10:48:15.403195700Z",
     "start_time": "2024-07-24T10:48:13.048385Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([64, 3, 128, 128])\n",
      "torch.Size([64])\n"
     ]
    }
   ],
   "source": [
    "for imgs, labels in train_loader:\n",
    "    print(imgs.shape)\n",
    "    print(labels.shape)\n",
    "    break"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 864\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.weight\tparamerters num: 9216\n",
      "conv2.bias\tparamerters num: 32\n",
      "conv3.weight\tparamerters num: 18432\n",
      "conv3.bias\tparamerters num: 64\n",
      "conv4.weight\tparamerters num: 36864\n",
      "conv4.bias\tparamerters num: 64\n",
      "conv5.weight\tparamerters num: 73728\n",
      "conv5.bias\tparamerters num: 128\n",
      "conv6.weight\tparamerters num: 147456\n",
      "conv6.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 4194304\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "source": [
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self, num_classes=10, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=\"same\")\n",
    "        self.pool = nn.MaxPool2d(2, 2)\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=\"same\")\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=\"same\")\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (3, 128, 128) so the flatten output shape is 128 * 16 * 16\n",
    "        self.fc1 = nn.Linear(128 * 16 * 16, 128)\n",
    "        self.fc2 = nn.Linear(128, num_classes)\n",
    "        \n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x)))))\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x)))))\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x)))))\n",
    "        x = self.flatten(x)\n",
    "        x = act(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "    \n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\")\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-04-14 21:09:33.058873: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX_VNNI FMA\n",
      "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "481dddc81fe84be3afc1853a2c537f47",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/360 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 14 / global_step 252\n"
     ]
    }
   ],
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"relu\"\n",
    "model = CNN(num_classes=10, activation=activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.001, eps=1e-7)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/monkeys-cnn-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 3, img_h, img_w])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/monkeys-cnn-{activation}\", save_step=len(train_loader), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=5)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_loader)\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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uXMSFBERl6JxSaR2Xs4OQMSVZGZmMnXqVJ5++mmuv/56CgoKWLduHdOmTSM9PZ38/HzeeOMNAMLDw7FarYwfP57ExETWrVuHl5cXf/rTn5gwYQI7d+7Ex8cHgDVr1uDn50dycjJpaWnMmDGDiIgI/vznPzszXRERaeM0LonUTYWOSANkZmZSUVHBDTfcQFxcHAADBgwAwN/fn7KyMqKjox37//vf/8Zut/P6669jMpkAeOONNwgNDSU5OZlx48YB4OPjw5IlSwgICKBfv348/vjjzJ07lyeeeAKzWTdeRUSkdhqXROqmd6pIAyQkJDBmzBgGDBjAzTffzOLFizlz5kyd++/YsYMDBw4QFBREYGAggYGBhIeHU1paysGDB2ucNyAgwPF1YmIihYWFZGRktGg+IiLi2jQuidRNd3REGsBisZCUlMT69etZvXo1L730Eg8//DAbN26sdf/CwkKGDh3KO++8c85r7du3b+lwRUTEzWlcEqmbCh2RBjKZTIwaNYpRo0Yxf/584uLiWL58OT4+Pthsthr7DhkyhKVLl9KhQweCg4PrPOeOHTsoKSnB398fgA0bNhAYGEjnzp1bNBcREXF9GpdEaqepayINsHHjRv7yl7+wZcsW0tPT+fjjjzl58iR9+/ala9eu7Ny5k/3795OTk4PVauX2228nMjKSSZMmsW7dOg4fPkxycjL3338/R48edZy3vLycX//61+zZs4fPPvuMBQsWMHv2bM2DFhGR89K4JFI33dERaYDg4GDWrl3LCy+8QH5+PnFxcfz1r39l4sSJDBs2jOTkZIYNG0ZhYSFff/01V1xxBWvXruXBBx/khhtuoKCggI4dOzJmzJgav0kbM2YMvXr1YvTo0ZSVlTF16lT++Mc/Oi9RERFxCRqXROpmMgzDcHYQIp7srrvuIjc3lxUrVjg7FBEREY1L4jZ0/1FERERERNyOCh0REREREXE7mromIiIiIiJuR3d0RERERETE7ajQERERERERt6NCR0RERERE3I4KHRERERERcTsqdERERERExO2o0BEREREREbejQkdERERERNyOCh0REREREXE7KnRERERERMTt/H+XMt1Z/PE1LwAAAABJRU5ErkJggg==",
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       "  \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"595.303125pt\" height=\"321.95625pt\" viewBox=\"0 0 595.303125 321.95625\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n",
       " <metadata>\n",
       "  <rdf:RDF xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:cc=\"http://creativecommons.org/ns#\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n",
       "   <cc:Work>\n",
       "    <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\"/>\n",
       "    <dc:date>2023-04-14T21:10:36.165935</dc:date>\n",
       "    <dc:format>image/svg+xml</dc:format>\n",
       "    <dc:creator>\n",
       "     <cc:Agent>\n",
       "      <dc:title>Matplotlib v3.6.3, https://matplotlib.org/</dc:title>\n",
       "     </cc:Agent>\n",
       "    </dc:creator>\n",
       "   </cc:Work>\n",
       "  </rdf:RDF>\n",
       " </metadata>\n",
       " <defs>\n",
       "  <style type=\"text/css\">*{stroke-linejoin: round; stroke-linecap: butt}</style>\n",
       " </defs>\n",
       " <g id=\"figure_1\">\n",
       "  <g id=\"patch_1\">\n",
       "   <path d=\"M -0 321.95625 \n",
       "L 595.303125 321.95625 \n",
       "L 595.303125 0 \n",
       "L -0 0 \n",
       "z\n",
       "\" style=\"fill: #ffffff\"/>\n",
       "  </g>\n",
       "  <g id=\"axes_1\">\n",
       "   <g id=\"patch_2\">\n",
       "    <path d=\"M 30.103125 284.4 \n",
       "L 283.739489 284.4 \n",
       "L 283.739489 7.2 \n",
       "L 30.103125 7.2 \n",
       "z\n",
       "\" style=\"fill: #ffffff\"/>\n",
       "   </g>\n",
       "   <g id=\"matplotlib.axis_1\">\n",
       "    <g id=\"xtick_1\">\n",
       "     <g id=\"line2d_1\">\n",
       "      <path d=\"M 41.632051 284.4 \n",
       "L 41.632051 7.2 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_2\">\n",
       "      <defs>\n",
       "       <path id=\"m6b16dfc6cd\" d=\"M 0 0 \n",
       "L 0 3.5 \n",
       "\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </defs>\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"41.632051\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_1\">\n",
       "      <!-- 0 -->\n",
       "      <g transform=\"translate(38.450801 298.998438) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-30\" d=\"M 2034 4250 \n",
       "Q 1547 4250 1301 3770 \n",
       "Q 1056 3291 1056 2328 \n",
       "Q 1056 1369 1301 889 \n",
       "Q 1547 409 2034 409 \n",
       "Q 2525 409 2770 889 \n",
       "Q 3016 1369 3016 2328 \n",
       "Q 3016 3291 2770 3770 \n",
       "Q 2525 4250 2034 4250 \n",
       "z\n",
       "M 2034 4750 \n",
       "Q 2819 4750 3233 4129 \n",
       "Q 3647 3509 3647 2328 \n",
       "Q 3647 1150 3233 529 \n",
       "Q 2819 -91 2034 -91 \n",
       "Q 1250 -91 836 529 \n",
       "Q 422 1150 422 2328 \n",
       "Q 422 3509 836 4129 \n",
       "Q 1250 4750 2034 4750 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_2\">\n",
       "     <g id=\"line2d_3\">\n",
       "      <path d=\"M 87.381755 284.4 \n",
       "L 87.381755 7.2 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_4\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"87.381755\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_2\">\n",
       "      <!-- 50 -->\n",
       "      <g transform=\"translate(81.019255 298.998438) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-35\" d=\"M 691 4666 \n",
       "L 3169 4666 \n",
       "L 3169 4134 \n",
       "L 1269 4134 \n",
       "L 1269 2991 \n",
       "Q 1406 3038 1543 3061 \n",
       "Q 1681 3084 1819 3084 \n",
       "Q 2600 3084 3056 2656 \n",
       "Q 3513 2228 3513 1497 \n",
       "Q 3513 744 3044 326 \n",
       "Q 2575 -91 1722 -91 \n",
       "Q 1428 -91 1123 -41 \n",
       "Q 819 9 494 109 \n",
       "L 494 744 \n",
       "Q 775 591 1075 516 \n",
       "Q 1375 441 1709 441 \n",
       "Q 2250 441 2565 725 \n",
       "Q 2881 1009 2881 1497 \n",
       "Q 2881 1984 2565 2268 \n",
       "Q 2250 2553 1709 2553 \n",
       "Q 1456 2553 1204 2497 \n",
       "Q 953 2441 691 2322 \n",
       "L 691 4666 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-35\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"63.623047\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_3\">\n",
       "     <g id=\"line2d_5\">\n",
       "      <path d=\"M 133.13146 284.4 \n",
       "L 133.13146 7.2 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_6\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"133.13146\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_3\">\n",
       "      <!-- 100 -->\n",
       "      <g transform=\"translate(123.58771 298.998438) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-31\" d=\"M 794 531 \n",
       "L 1825 531 \n",
       "L 1825 4091 \n",
       "L 703 3866 \n",
       "L 703 4441 \n",
       "L 1819 4666 \n",
       "L 2450 4666 \n",
       "L 2450 531 \n",
       "L 3481 531 \n",
       "L 3481 0 \n",
       "L 794 0 \n",
       "L 794 531 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_4\">\n",
       "     <g id=\"line2d_7\">\n",
       "      <path d=\"M 178.881165 284.4 \n",
       "L 178.881165 7.2 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_8\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"178.881165\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_4\">\n",
       "      <!-- 150 -->\n",
       "      <g transform=\"translate(169.337415 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_5\">\n",
       "     <g id=\"line2d_9\">\n",
       "      <path d=\"M 224.63087 284.4 \n",
       "L 224.63087 7.2 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_10\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"224.63087\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_5\">\n",
       "      <!-- 200 -->\n",
       "      <g transform=\"translate(215.08712 298.998438) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-32\" d=\"M 1228 531 \n",
       "L 3431 531 \n",
       "L 3431 0 \n",
       "L 469 0 \n",
       "L 469 531 \n",
       "Q 828 903 1448 1529 \n",
       "Q 2069 2156 2228 2338 \n",
       "Q 2531 2678 2651 2914 \n",
       "Q 2772 3150 2772 3378 \n",
       "Q 2772 3750 2511 3984 \n",
       "Q 2250 4219 1831 4219 \n",
       "Q 1534 4219 1204 4116 \n",
       "Q 875 4013 500 3803 \n",
       "L 500 4441 \n",
       "Q 881 4594 1212 4672 \n",
       "Q 1544 4750 1819 4750 \n",
       "Q 2544 4750 2975 4387 \n",
       "Q 3406 4025 3406 3419 \n",
       "Q 3406 3131 3298 2873 \n",
       "Q 3191 2616 2906 2266 \n",
       "Q 2828 2175 2409 1742 \n",
       "Q 1991 1309 1228 531 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-32\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_6\">\n",
       "     <g id=\"line2d_11\">\n",
       "      <path d=\"M 270.380575 284.4 \n",
       "L 270.380575 7.2 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_12\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"270.380575\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_6\">\n",
       "      <!-- 250 -->\n",
       "      <g transform=\"translate(260.836825 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-32\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"text_7\">\n",
       "     <!-- step -->\n",
       "     <g transform=\"translate(146.105682 312.676562) scale(0.1 -0.1)\">\n",
       "      <defs>\n",
       "       <path id=\"DejaVuSans-73\" d=\"M 2834 3397 \n",
       "L 2834 2853 \n",
       "Q 2591 2978 2328 3040 \n",
       "Q 2066 3103 1784 3103 \n",
       "Q 1356 3103 1142 2972 \n",
       "Q 928 2841 928 2578 \n",
       "Q 928 2378 1081 2264 \n",
       "Q 1234 2150 1697 2047 \n",
       "L 1894 2003 \n",
       "Q 2506 1872 2764 1633 \n",
       "Q 3022 1394 3022 966 \n",
       "Q 3022 478 2636 193 \n",
       "Q 2250 -91 1575 -91 \n",
       "Q 1294 -91 989 -36 \n",
       "Q 684 19 347 128 \n",
       "L 347 722 \n",
       "Q 666 556 975 473 \n",
       "Q 1284 391 1588 391 \n",
       "Q 1994 391 2212 530 \n",
       "Q 2431 669 2431 922 \n",
       "Q 2431 1156 2273 1281 \n",
       "Q 2116 1406 1581 1522 \n",
       "L 1381 1569 \n",
       "Q 847 1681 609 1914 \n",
       "Q 372 2147 372 2553 \n",
       "Q 372 3047 722 3315 \n",
       "Q 1072 3584 1716 3584 \n",
       "Q 2034 3584 2315 3537 \n",
       "Q 2597 3491 2834 3397 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-74\" d=\"M 1172 4494 \n",
       "L 1172 3500 \n",
       "L 2356 3500 \n",
       "L 2356 3053 \n",
       "L 1172 3053 \n",
       "L 1172 1153 \n",
       "Q 1172 725 1289 603 \n",
       "Q 1406 481 1766 481 \n",
       "L 2356 481 \n",
       "L 2356 0 \n",
       "L 1766 0 \n",
       "Q 1100 0 847 248 \n",
       "Q 594 497 594 1153 \n",
       "L 594 3053 \n",
       "L 172 3053 \n",
       "L 172 3500 \n",
       "L 594 3500 \n",
       "L 594 4494 \n",
       "L 1172 4494 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-65\" d=\"M 3597 1894 \n",
       "L 3597 1613 \n",
       "L 953 1613 \n",
       "Q 991 1019 1311 708 \n",
       "Q 1631 397 2203 397 \n",
       "Q 2534 397 2845 478 \n",
       "Q 3156 559 3463 722 \n",
       "L 3463 178 \n",
       "Q 3153 47 2828 -22 \n",
       "Q 2503 -91 2169 -91 \n",
       "Q 1331 -91 842 396 \n",
       "Q 353 884 353 1716 \n",
       "Q 353 2575 817 3079 \n",
       "Q 1281 3584 2069 3584 \n",
       "Q 2775 3584 3186 3129 \n",
       "Q 3597 2675 3597 1894 \n",
       "z\n",
       "M 3022 2063 \n",
       "Q 3016 2534 2758 2815 \n",
       "Q 2500 3097 2075 3097 \n",
       "Q 1594 3097 1305 2825 \n",
       "Q 1016 2553 972 2059 \n",
       "L 3022 2063 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-70\" d=\"M 1159 525 \n",
       "L 1159 -1331 \n",
       "L 581 -1331 \n",
       "L 581 3500 \n",
       "L 1159 3500 \n",
       "L 1159 2969 \n",
       "Q 1341 3281 1617 3432 \n",
       "Q 1894 3584 2278 3584 \n",
       "Q 2916 3584 3314 3078 \n",
       "Q 3713 2572 3713 1747 \n",
       "Q 3713 922 3314 415 \n",
       "Q 2916 -91 2278 -91 \n",
       "Q 1894 -91 1617 61 \n",
       "Q 1341 213 1159 525 \n",
       "z\n",
       "M 3116 1747 \n",
       "Q 3116 2381 2855 2742 \n",
       "Q 2594 3103 2138 3103 \n",
       "Q 1681 3103 1420 2742 \n",
       "Q 1159 2381 1159 1747 \n",
       "Q 1159 1113 1420 752 \n",
       "Q 1681 391 2138 391 \n",
       "Q 2594 391 2855 752 \n",
       "Q 3116 1113 3116 1747 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "      </defs>\n",
       "      <use xlink:href=\"#DejaVuSans-73\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-74\" x=\"52.099609\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-65\" x=\"91.308594\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-70\" x=\"152.832031\"/>\n",
       "     </g>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"matplotlib.axis_2\">\n",
       "    <g id=\"ytick_1\">\n",
       "     <g id=\"line2d_13\">\n",
       "      <path d=\"M 30.103125 272.558714 \n",
       "L 283.739489 272.558714 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_14\">\n",
       "      <defs>\n",
       "       <path id=\"mbcedbd830e\" d=\"M 0 0 \n",
       "L -3.5 0 \n",
       "\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </defs>\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"30.103125\" y=\"272.558714\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_8\">\n",
       "      <!-- 0.0 -->\n",
       "      <g transform=\"translate(7.2 276.357933) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-2e\" d=\"M 684 794 \n",
       "L 1344 794 \n",
       "L 1344 0 \n",
       "L 684 0 \n",
       "L 684 794 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_2\">\n",
       "     <g id=\"line2d_15\">\n",
       "      <path d=\"M 30.103125 227.095815 \n",
       "L 283.739489 227.095815 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_16\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"30.103125\" y=\"227.095815\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_9\">\n",
       "      <!-- 0.5 -->\n",
       "      <g transform=\"translate(7.2 230.895034) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_3\">\n",
       "     <g id=\"line2d_17\">\n",
       "      <path d=\"M 30.103125 181.632916 \n",
       "L 283.739489 181.632916 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_18\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"30.103125\" y=\"181.632916\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_10\">\n",
       "      <!-- 1.0 -->\n",
       "      <g transform=\"translate(7.2 185.432134) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_4\">\n",
       "     <g id=\"line2d_19\">\n",
       "      <path d=\"M 30.103125 136.170016 \n",
       "L 283.739489 136.170016 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_20\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"30.103125\" y=\"136.170016\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_11\">\n",
       "      <!-- 1.5 -->\n",
       "      <g transform=\"translate(7.2 139.969235) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_5\">\n",
       "     <g id=\"line2d_21\">\n",
       "      <path d=\"M 30.103125 90.707117 \n",
       "L 283.739489 90.707117 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_22\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"30.103125\" y=\"90.707117\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_12\">\n",
       "      <!-- 2.0 -->\n",
       "      <g transform=\"translate(7.2 94.506336) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-32\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_6\">\n",
       "     <g id=\"line2d_23\">\n",
       "      <path d=\"M 30.103125 45.244217 \n",
       "L 283.739489 45.244217 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_24\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"30.103125\" y=\"45.244217\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_13\">\n",
       "      <!-- 2.5 -->\n",
       "      <g transform=\"translate(7.2 49.043436) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-32\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"line2d_25\">\n",
       "    <path d=\"M 41.632051 60.771263 \n",
       "L 50.781992 68.353652 \n",
       "L 59.931933 114.91234 \n",
       "L 69.081874 95.388166 \n",
       "L 78.231814 147.313256 \n",
       "L 87.381755 171.832415 \n",
       "L 96.531696 162.912512 \n",
       "L 105.681637 189.94294 \n",
       "L 114.831578 148.895801 \n",
       "L 123.981519 182.198592 \n",
       "L 133.13146 226.095877 \n",
       "L 142.281401 202.335229 \n",
       "L 151.431342 216.528186 \n",
       "L 160.581283 230.08334 \n",
       "L 169.731224 243.794117 \n",
       "L 178.881165 231.248009 \n",
       "L 188.031106 243.843092 \n",
       "L 197.181047 265.567641 \n",
       "L 206.330988 258.191801 \n",
       "L 215.480929 269.892853 \n",
       "L 224.63087 263.542968 \n",
       "L 233.780811 271.8 \n",
       "L 242.930752 264.782716 \n",
       "L 252.080693 260.73183 \n",
       "L 261.230634 269.848318 \n",
       "L 270.380575 270.889577 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"line2d_26\">\n",
       "    <path d=\"M 41.632051 19.8 \n",
       "L 58.101944 101.283225 \n",
       "L 74.571838 109.426359 \n",
       "L 91.041732 135.086239 \n",
       "L 107.511626 143.975081 \n",
       "L 123.981519 148.588743 \n",
       "L 140.451413 158.019092 \n",
       "L 156.921307 156.762867 \n",
       "L 173.391201 119.125656 \n",
       "L 189.861094 141.426359 \n",
       "L 206.330988 99.359196 \n",
       "L 222.800882 79.390561 \n",
       "L 239.270776 65.608917 \n",
       "L 255.740669 67.148827 \n",
       "L 272.210563 58.32124 \n",
       "\" clip-path=\"url(#p7335f94748)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_3\">\n",
       "    <path d=\"M 30.103125 284.4 \n",
       "L 30.103125 7.2 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_4\">\n",
       "    <path d=\"M 283.739489 284.4 \n",
       "L 283.739489 7.2 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_5\">\n",
       "    <path d=\"M 30.103125 284.4 \n",
       "L 283.739489 284.4 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_6\">\n",
       "    <path d=\"M 30.103125 7.2 \n",
       "L 283.739489 7.2 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"legend_1\">\n",
       "    <g id=\"patch_7\">\n",
       "     <path d=\"M 197.148864 45.1125 \n",
       "L 276.739489 45.1125 \n",
       "Q 278.739489 45.1125 278.739489 43.1125 \n",
       "L 278.739489 14.2 \n",
       "Q 278.739489 12.2 276.739489 12.2 \n",
       "L 197.148864 12.2 \n",
       "Q 195.148864 12.2 195.148864 14.2 \n",
       "L 195.148864 43.1125 \n",
       "Q 195.148864 45.1125 197.148864 45.1125 \n",
       "z\n",
       "\" style=\"fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-linejoin: miter\"/>\n",
       "    </g>\n",
       "    <g id=\"line2d_27\">\n",
       "     <path d=\"M 199.148864 20.298437 \n",
       "L 209.148864 20.298437 \n",
       "L 219.148864 20.298437 \n",
       "\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "    </g>\n",
       "    <g id=\"text_14\">\n",
       "     <!-- train_loss -->\n",
       "     <g transform=\"translate(227.148864 23.798437) scale(0.1 -0.1)\">\n",
       "      <defs>\n",
       "       <path id=\"DejaVuSans-72\" d=\"M 2631 2963 \n",
       "Q 2534 3019 2420 3045 \n",
       "Q 2306 3072 2169 3072 \n",
       "Q 1681 3072 1420 2755 \n",
       "Q 1159 2438 1159 1844 \n",
       "L 1159 0 \n",
       "L 581 0 \n",
       "L 581 3500 \n",
       "L 1159 3500 \n",
       "L 1159 2956 \n",
       "Q 1341 3275 1631 3429 \n",
       "Q 1922 3584 2338 3584 \n",
       "Q 2397 3584 2469 3576 \n",
       "Q 2541 3569 2628 3553 \n",
       "L 2631 2963 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-61\" d=\"M 2194 1759 \n",
       "Q 1497 1759 1228 1600 \n",
       "Q 959 1441 959 1056 \n",
       "Q 959 750 1161 570 \n",
       "Q 1363 391 1709 391 \n",
       "Q 2188 391 2477 730 \n",
       "Q 2766 1069 2766 1631 \n",
       "L 2766 1759 \n",
       "L 2194 1759 \n",
       "z\n",
       "M 3341 1997 \n",
       "L 3341 0 \n",
       "L 2766 0 \n",
       "L 2766 531 \n",
       "Q 2569 213 2275 61 \n",
       "Q 1981 -91 1556 -91 \n",
       "Q 1019 -91 701 211 \n",
       "Q 384 513 384 1019 \n",
       "Q 384 1609 779 1909 \n",
       "Q 1175 2209 1959 2209 \n",
       "L 2766 2209 \n",
       "L 2766 2266 \n",
       "Q 2766 2663 2505 2880 \n",
       "Q 2244 3097 1772 3097 \n",
       "Q 1472 3097 1187 3025 \n",
       "Q 903 2953 641 2809 \n",
       "L 641 3341 \n",
       "Q 956 3463 1253 3523 \n",
       "Q 1550 3584 1831 3584 \n",
       "Q 2591 3584 2966 3190 \n",
       "Q 3341 2797 3341 1997 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-69\" d=\"M 603 3500 \n",
       "L 1178 3500 \n",
       "L 1178 0 \n",
       "L 603 0 \n",
       "L 603 3500 \n",
       "z\n",
       "M 603 4863 \n",
       "L 1178 4863 \n",
       "L 1178 4134 \n",
       "L 603 4134 \n",
       "L 603 4863 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-6e\" d=\"M 3513 2113 \n",
       "L 3513 0 \n",
       "L 2938 0 \n",
       "L 2938 2094 \n",
       "Q 2938 2591 2744 2837 \n",
       "Q 2550 3084 2163 3084 \n",
       "Q 1697 3084 1428 2787 \n",
       "Q 1159 2491 1159 1978 \n",
       "L 1159 0 \n",
       "L 581 0 \n",
       "L 581 3500 \n",
       "L 1159 3500 \n",
       "L 1159 2956 \n",
       "Q 1366 3272 1645 3428 \n",
       "Q 1925 3584 2291 3584 \n",
       "Q 2894 3584 3203 3211 \n",
       "Q 3513 2838 3513 2113 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-5f\" d=\"M 3263 -1063 \n",
       "L 3263 -1509 \n",
       "L -63 -1509 \n",
       "L -63 -1063 \n",
       "L 3263 -1063 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-6c\" d=\"M 603 4863 \n",
       "L 1178 4863 \n",
       "L 1178 0 \n",
       "L 603 0 \n",
       "L 603 4863 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       <path id=\"DejaVuSans-6f\" d=\"M 1959 3097 \n",
       "Q 1497 3097 1228 2736 \n",
       "Q 959 2375 959 1747 \n",
       "Q 959 1119 1226 758 \n",
       "Q 1494 397 1959 397 \n",
       "Q 2419 397 2687 759 \n",
       "Q 2956 1122 2956 1747 \n",
       "Q 2956 2369 2687 2733 \n",
       "Q 2419 3097 1959 3097 \n",
       "z\n",
       "M 1959 3584 \n",
       "Q 2709 3584 3137 3096 \n",
       "Q 3566 2609 3566 1747 \n",
       "Q 3566 888 3137 398 \n",
       "Q 2709 -91 1959 -91 \n",
       "Q 1206 -91 779 398 \n",
       "Q 353 888 353 1747 \n",
       "Q 353 2609 779 3096 \n",
       "Q 1206 3584 1959 3584 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "      </defs>\n",
       "      <use xlink:href=\"#DejaVuSans-74\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-72\" x=\"39.208984\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-61\" x=\"80.322266\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-69\" x=\"141.601562\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6e\" x=\"169.384766\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-5f\" x=\"232.763672\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6c\" x=\"282.763672\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6f\" x=\"310.546875\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-73\" x=\"371.728516\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-73\" x=\"423.828125\"/>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"line2d_28\">\n",
       "     <path d=\"M 199.148864 35.254687 \n",
       "L 209.148864 35.254687 \n",
       "L 219.148864 35.254687 \n",
       "\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "    </g>\n",
       "    <g id=\"text_15\">\n",
       "     <!-- val_loss -->\n",
       "     <g transform=\"translate(227.148864 38.754687) scale(0.1 -0.1)\">\n",
       "      <defs>\n",
       "       <path id=\"DejaVuSans-76\" d=\"M 191 3500 \n",
       "L 800 3500 \n",
       "L 1894 563 \n",
       "L 2988 3500 \n",
       "L 3597 3500 \n",
       "L 2284 0 \n",
       "L 1503 0 \n",
       "L 191 3500 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "      </defs>\n",
       "      <use xlink:href=\"#DejaVuSans-76\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-61\" x=\"59.179688\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6c\" x=\"120.458984\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-5f\" x=\"148.242188\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6c\" x=\"198.242188\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6f\" x=\"226.025391\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-73\" x=\"287.207031\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-73\" x=\"339.306641\"/>\n",
       "     </g>\n",
       "    </g>\n",
       "   </g>\n",
       "  </g>\n",
       "  <g id=\"axes_2\">\n",
       "   <g id=\"patch_8\">\n",
       "    <path d=\"M 334.466761 284.4 \n",
       "L 588.103125 284.4 \n",
       "L 588.103125 7.2 \n",
       "L 334.466761 7.2 \n",
       "z\n",
       "\" style=\"fill: #ffffff\"/>\n",
       "   </g>\n",
       "   <g id=\"matplotlib.axis_3\">\n",
       "    <g id=\"xtick_7\">\n",
       "     <g id=\"line2d_29\">\n",
       "      <path d=\"M 345.995687 284.4 \n",
       "L 345.995687 7.2 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_30\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"345.995687\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_16\">\n",
       "      <!-- 0 -->\n",
       "      <g transform=\"translate(342.814437 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_8\">\n",
       "     <g id=\"line2d_31\">\n",
       "      <path d=\"M 391.745392 284.4 \n",
       "L 391.745392 7.2 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_32\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"391.745392\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_17\">\n",
       "      <!-- 50 -->\n",
       "      <g transform=\"translate(385.382892 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-35\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"63.623047\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_9\">\n",
       "     <g id=\"line2d_33\">\n",
       "      <path d=\"M 437.495097 284.4 \n",
       "L 437.495097 7.2 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_34\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"437.495097\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_18\">\n",
       "      <!-- 100 -->\n",
       "      <g transform=\"translate(427.951347 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_10\">\n",
       "     <g id=\"line2d_35\">\n",
       "      <path d=\"M 483.244802 284.4 \n",
       "L 483.244802 7.2 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_36\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"483.244802\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_19\">\n",
       "      <!-- 150 -->\n",
       "      <g transform=\"translate(473.701052 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_11\">\n",
       "     <g id=\"line2d_37\">\n",
       "      <path d=\"M 528.994506 284.4 \n",
       "L 528.994506 7.2 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_38\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"528.994506\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_20\">\n",
       "      <!-- 200 -->\n",
       "      <g transform=\"translate(519.450756 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-32\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"xtick_12\">\n",
       "     <g id=\"line2d_39\">\n",
       "      <path d=\"M 574.744211 284.4 \n",
       "L 574.744211 7.2 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_40\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#m6b16dfc6cd\" x=\"574.744211\" y=\"284.4\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_21\">\n",
       "      <!-- 250 -->\n",
       "      <g transform=\"translate(565.200461 298.998438) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-32\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-35\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"127.246094\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"text_22\">\n",
       "     <!-- step -->\n",
       "     <g transform=\"translate(450.469318 312.676562) scale(0.1 -0.1)\">\n",
       "      <use xlink:href=\"#DejaVuSans-73\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-74\" x=\"52.099609\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-65\" x=\"91.308594\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-70\" x=\"152.832031\"/>\n",
       "     </g>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"matplotlib.axis_4\">\n",
       "    <g id=\"ytick_7\">\n",
       "     <g id=\"line2d_41\">\n",
       "      <path d=\"M 334.466761 238.484746 \n",
       "L 588.103125 238.484746 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_42\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"334.466761\" y=\"238.484746\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_23\">\n",
       "      <!-- 0.2 -->\n",
       "      <g transform=\"translate(311.563636 242.283965) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-32\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_8\">\n",
       "     <g id=\"line2d_43\">\n",
       "      <path d=\"M 334.466761 183.813559 \n",
       "L 588.103125 183.813559 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_44\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"334.466761\" y=\"183.813559\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_24\">\n",
       "      <!-- 0.4 -->\n",
       "      <g transform=\"translate(311.563636 187.612778) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-34\" d=\"M 2419 4116 \n",
       "L 825 1625 \n",
       "L 2419 1625 \n",
       "L 2419 4116 \n",
       "z\n",
       "M 2253 4666 \n",
       "L 3047 4666 \n",
       "L 3047 1625 \n",
       "L 3713 1625 \n",
       "L 3713 1100 \n",
       "L 3047 1100 \n",
       "L 3047 0 \n",
       "L 2419 0 \n",
       "L 2419 1100 \n",
       "L 313 1100 \n",
       "L 313 1709 \n",
       "L 2253 4666 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-34\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_9\">\n",
       "     <g id=\"line2d_45\">\n",
       "      <path d=\"M 334.466761 129.142373 \n",
       "L 588.103125 129.142373 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_46\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"334.466761\" y=\"129.142373\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_25\">\n",
       "      <!-- 0.6 -->\n",
       "      <g transform=\"translate(311.563636 132.941592) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-36\" d=\"M 2113 2584 \n",
       "Q 1688 2584 1439 2293 \n",
       "Q 1191 2003 1191 1497 \n",
       "Q 1191 994 1439 701 \n",
       "Q 1688 409 2113 409 \n",
       "Q 2538 409 2786 701 \n",
       "Q 3034 994 3034 1497 \n",
       "Q 3034 2003 2786 2293 \n",
       "Q 2538 2584 2113 2584 \n",
       "z\n",
       "M 3366 4563 \n",
       "L 3366 3988 \n",
       "Q 3128 4100 2886 4159 \n",
       "Q 2644 4219 2406 4219 \n",
       "Q 1781 4219 1451 3797 \n",
       "Q 1122 3375 1075 2522 \n",
       "Q 1259 2794 1537 2939 \n",
       "Q 1816 3084 2150 3084 \n",
       "Q 2853 3084 3261 2657 \n",
       "Q 3669 2231 3669 1497 \n",
       "Q 3669 778 3244 343 \n",
       "Q 2819 -91 2113 -91 \n",
       "Q 1303 -91 875 529 \n",
       "Q 447 1150 447 2328 \n",
       "Q 447 3434 972 4092 \n",
       "Q 1497 4750 2381 4750 \n",
       "Q 2619 4750 2861 4703 \n",
       "Q 3103 4656 3366 4563 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-36\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_10\">\n",
       "     <g id=\"line2d_47\">\n",
       "      <path d=\"M 334.466761 74.471186 \n",
       "L 588.103125 74.471186 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_48\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"334.466761\" y=\"74.471186\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_26\">\n",
       "      <!-- 0.8 -->\n",
       "      <g transform=\"translate(311.563636 78.270405) scale(0.1 -0.1)\">\n",
       "       <defs>\n",
       "        <path id=\"DejaVuSans-38\" d=\"M 2034 2216 \n",
       "Q 1584 2216 1326 1975 \n",
       "Q 1069 1734 1069 1313 \n",
       "Q 1069 891 1326 650 \n",
       "Q 1584 409 2034 409 \n",
       "Q 2484 409 2743 651 \n",
       "Q 3003 894 3003 1313 \n",
       "Q 3003 1734 2745 1975 \n",
       "Q 2488 2216 2034 2216 \n",
       "z\n",
       "M 1403 2484 \n",
       "Q 997 2584 770 2862 \n",
       "Q 544 3141 544 3541 \n",
       "Q 544 4100 942 4425 \n",
       "Q 1341 4750 2034 4750 \n",
       "Q 2731 4750 3128 4425 \n",
       "Q 3525 4100 3525 3541 \n",
       "Q 3525 3141 3298 2862 \n",
       "Q 3072 2584 2669 2484 \n",
       "Q 3125 2378 3379 2068 \n",
       "Q 3634 1759 3634 1313 \n",
       "Q 3634 634 3220 271 \n",
       "Q 2806 -91 2034 -91 \n",
       "Q 1263 -91 848 271 \n",
       "Q 434 634 434 1313 \n",
       "Q 434 1759 690 2068 \n",
       "Q 947 2378 1403 2484 \n",
       "z\n",
       "M 1172 3481 \n",
       "Q 1172 3119 1398 2916 \n",
       "Q 1625 2713 2034 2713 \n",
       "Q 2441 2713 2670 2916 \n",
       "Q 2900 3119 2900 3481 \n",
       "Q 2900 3844 2670 4047 \n",
       "Q 2441 4250 2034 4250 \n",
       "Q 1625 4250 1398 4047 \n",
       "Q 1172 3844 1172 3481 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "       </defs>\n",
       "       <use xlink:href=\"#DejaVuSans-30\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-38\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"ytick_11\">\n",
       "     <g id=\"line2d_49\">\n",
       "      <path d=\"M 334.466761 19.8 \n",
       "L 588.103125 19.8 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n",
       "     </g>\n",
       "     <g id=\"line2d_50\">\n",
       "      <g>\n",
       "       <use xlink:href=\"#mbcedbd830e\" x=\"334.466761\" y=\"19.8\" style=\"stroke: #000000; stroke-width: 0.8\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "     <g id=\"text_27\">\n",
       "      <!-- 1.0 -->\n",
       "      <g transform=\"translate(311.563636 23.599219) scale(0.1 -0.1)\">\n",
       "       <use xlink:href=\"#DejaVuSans-31\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-2e\" x=\"63.623047\"/>\n",
       "       <use xlink:href=\"#DejaVuSans-30\" x=\"95.410156\"/>\n",
       "      </g>\n",
       "     </g>\n",
       "    </g>\n",
       "   </g>\n",
       "   <g id=\"line2d_51\">\n",
       "    <path d=\"M 345.995687 271.8 \n",
       "L 355.145628 246.172881 \n",
       "L 364.295569 177.833898 \n",
       "L 373.44551 190.647458 \n",
       "L 382.595451 160.749153 \n",
       "L 391.745392 113.766102 \n",
       "L 400.895333 143.664407 \n",
       "L 410.045274 96.681356 \n",
       "L 419.195215 152.20678 \n",
       "L 428.345156 109.494915 \n",
       "L 437.495097 62.511864 \n",
       "L 446.645038 88.138983 \n",
       "L 455.794979 66.783051 \n",
       "L 464.94492 45.427119 \n",
       "L 474.094861 53.969492 \n",
       "L 483.244802 58.240678 \n",
       "L 492.394742 58.240678 \n",
       "L 501.544683 28.342373 \n",
       "L 510.694624 36.884746 \n",
       "L 519.844565 19.8 \n",
       "L 528.994506 28.342373 \n",
       "L 538.144447 19.8 \n",
       "L 547.294388 28.342373 \n",
       "L 556.444329 32.613559 \n",
       "L 565.59427 24.071186 \n",
       "L 574.744211 19.8 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"line2d_52\">\n",
       "    <path d=\"M 345.995687 264.011366 \n",
       "L 362.465581 198.687338 \n",
       "L 378.935474 184.617547 \n",
       "L 395.405368 150.448056 \n",
       "L 411.875262 149.443071 \n",
       "L 428.345156 149.443071 \n",
       "L 444.815049 139.39322 \n",
       "L 461.284943 127.3334 \n",
       "L 477.754837 127.3334 \n",
       "L 494.224731 113.263609 \n",
       "L 510.694624 131.35334 \n",
       "L 527.164518 135.37328 \n",
       "L 543.634412 133.36331 \n",
       "L 560.104306 122.308475 \n",
       "L 576.574199 119.293519 \n",
       "\" clip-path=\"url(#pbed78696e3)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_9\">\n",
       "    <path d=\"M 334.466761 284.4 \n",
       "L 334.466761 7.2 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_10\">\n",
       "    <path d=\"M 588.103125 284.4 \n",
       "L 588.103125 7.2 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_11\">\n",
       "    <path d=\"M 334.466761 284.4 \n",
       "L 588.103125 284.4 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"patch_12\">\n",
       "    <path d=\"M 334.466761 7.2 \n",
       "L 588.103125 7.2 \n",
       "\" style=\"fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square\"/>\n",
       "   </g>\n",
       "   <g id=\"legend_2\">\n",
       "    <g id=\"patch_13\">\n",
       "     <path d=\"M 341.466761 45.1125 \n",
       "L 418.866761 45.1125 \n",
       "Q 420.866761 45.1125 420.866761 43.1125 \n",
       "L 420.866761 14.2 \n",
       "Q 420.866761 12.2 418.866761 12.2 \n",
       "L 341.466761 12.2 \n",
       "Q 339.466761 12.2 339.466761 14.2 \n",
       "L 339.466761 43.1125 \n",
       "Q 339.466761 45.1125 341.466761 45.1125 \n",
       "z\n",
       "\" style=\"fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-linejoin: miter\"/>\n",
       "    </g>\n",
       "    <g id=\"line2d_53\">\n",
       "     <path d=\"M 343.466761 20.298437 \n",
       "L 353.466761 20.298437 \n",
       "L 363.466761 20.298437 \n",
       "\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "    </g>\n",
       "    <g id=\"text_28\">\n",
       "     <!-- train_acc -->\n",
       "     <g transform=\"translate(371.466761 23.798437) scale(0.1 -0.1)\">\n",
       "      <defs>\n",
       "       <path id=\"DejaVuSans-63\" d=\"M 3122 3366 \n",
       "L 3122 2828 \n",
       "Q 2878 2963 2633 3030 \n",
       "Q 2388 3097 2138 3097 \n",
       "Q 1578 3097 1268 2742 \n",
       "Q 959 2388 959 1747 \n",
       "Q 959 1106 1268 751 \n",
       "Q 1578 397 2138 397 \n",
       "Q 2388 397 2633 464 \n",
       "Q 2878 531 3122 666 \n",
       "L 3122 134 \n",
       "Q 2881 22 2623 -34 \n",
       "Q 2366 -91 2075 -91 \n",
       "Q 1284 -91 818 406 \n",
       "Q 353 903 353 1747 \n",
       "Q 353 2603 823 3093 \n",
       "Q 1294 3584 2113 3584 \n",
       "Q 2378 3584 2631 3529 \n",
       "Q 2884 3475 3122 3366 \n",
       "z\n",
       "\" transform=\"scale(0.015625)\"/>\n",
       "      </defs>\n",
       "      <use xlink:href=\"#DejaVuSans-74\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-72\" x=\"39.208984\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-61\" x=\"80.322266\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-69\" x=\"141.601562\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6e\" x=\"169.384766\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-5f\" x=\"232.763672\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-61\" x=\"282.763672\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-63\" x=\"344.042969\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-63\" x=\"399.023438\"/>\n",
       "     </g>\n",
       "    </g>\n",
       "    <g id=\"line2d_54\">\n",
       "     <path d=\"M 343.466761 35.254687 \n",
       "L 353.466761 35.254687 \n",
       "L 363.466761 35.254687 \n",
       "\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n",
       "    </g>\n",
       "    <g id=\"text_29\">\n",
       "     <!-- val_acc -->\n",
       "     <g transform=\"translate(371.466761 38.754687) scale(0.1 -0.1)\">\n",
       "      <use xlink:href=\"#DejaVuSans-76\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-61\" x=\"59.179688\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-6c\" x=\"120.458984\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-5f\" x=\"148.242188\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-61\" x=\"198.242188\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-63\" x=\"259.521484\"/>\n",
       "      <use xlink:href=\"#DejaVuSans-63\" x=\"314.501953\"/>\n",
       "     </g>\n",
       "    </g>\n",
       "   </g>\n",
       "  </g>\n",
       " </g>\n",
       " <defs>\n",
       "  <clipPath id=\"p7335f94748\">\n",
       "   <rect x=\"30.103125\" y=\"7.2\" width=\"253.636364\" height=\"277.2\"/>\n",
       "  </clipPath>\n",
       "  <clipPath id=\"pbed78696e3\">\n",
       "   <rect x=\"334.466761\" y=\"7.2\" width=\"253.636364\" height=\"277.2\"/>\n",
       "  </clipPath>\n",
       " </defs>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=10)  #横坐标是 steps"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     1.4422\n",
      "accuracy: 0.6581\n"
     ]
    }
   ],
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/monkeys-cnn-{activation}/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, val_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
